from datetime import datetime

from sqlalchemy import or_, and_
# https://www.cnblogs.com/chenxi67/p/10376617.html

# 在FLASK-SQLALCHEMY 的FILTER中如何使用OR和AND来组合多种条件查询

from app.middlerware.Jwt import UserToken
from app.models import db
from app.models.user import User
from app.utils.logger import Log


class UserDao(object):

    log = Log("UserDao")

    # 注册 Dao
    @staticmethod
    def register_user(username, name, password, email):
        '''
        User.query.filter这行代码的意思是，找出所有username或email已经存在的用户，
        如果有，则抛出异常，没有则直接通过orm插入这行数据。
        :param username: 用户名
        :param name: 姓名
        :param password: 密码
        :param email: 邮箱
        :return:

        '''
        # 第一步： 先判断是否已注册过
        try:
            users = User.query.filter(or_(User.username==username, User.email==email)).all()
            # 不存在则为空数组
            if users:
                raise Exception("用户名或邮箱已存在")

        # 第二步： 注册的时候给密码加盐
            pwd = UserToken.add_salt(password)
            # 在orm的世界里，我们实例化的user对象就是数据表中的一行数据
            user = User(username, name, pwd, email)
            db.session.add(user)
            # commit是将db_session中的所有指令一次性提交
            db.session.commit()
            UserDao.log.info(f"用户 {username} 注册成功！")
        # 方法二:
        #     user_list = [
        #         User(name="wang1"),
        #         User(name="wang2"),
        #         User(name="wang3")
        #     ]
        #     db_session.add_all(user_list)
        #     db_session.commit()
        #
        #     db_session.close()
        except Exception as e:
            UserDao.log.error(f"用户注册失败:{str(e)}")
            return str(e)
        return None

    @staticmethod
    def login(username, password):
        '''
        :param username:
        :param password:
        :return:
        '''
        try:
            # 先把前端传递过来的密码加盐
            pwd = UserToken.add_salt(password)
            # 从数据库里查询用户名密码匹配且没有被删除的用户
            user = User.query.filter_by(username=username, password=pwd, deleted_at=None).first()
            print(f"user ==> {user}")
            print(dir(user))
            print(user.__table__.columns)

            # print(dir(user.__table__))
            # print(type(user))
            UserDao.log.info(f" 当前登录的用户是: {user.name} ")
            # print(user.email)
            if not user:
                return None, "用户名或密码错误"

        # 成功登录后 更新用户的最后登录时间
            user.last_login_at = datetime.now()
            # 提交修改记录
            db.session.commit()
            # 注册完用户以后是没有返回User实例信息的，但是这个接口不同，
            # 用户登录以后，需要拿到用户的信息以及token给前端处理。
            # 用户实例并不是一个JSON对象，所以我们要为它做一些处理。
            # -->/handler/factory.py
            return user, None

        except Exception as e:
            UserDao.log.error(f"用户{username} 登陆失败: {str(e)}")
            return None, str(e)


    @staticmethod
    def list_users():
        try:
            users = User.query.filter_by(deleted_at=None).all()
            return users,None
        except Exception as e:
            UserDao.log.error(f"获取用户列表失败：{str(e)}")
            return [], str(e)
